package com.example.util;

import java.text.SimpleDateFormat;
import java.util.*;

public class IDCardGenerator {

    // 区域编码（省市区）
    private static final Map<String, String[]> AREA_CODES = new HashMap<>();

    static {
        // 省级区域编码（前2位）
        AREA_CODES.put("11", new String[]{"北京市"});
        AREA_CODES.put("12", new String[]{"天津市"});
        AREA_CODES.put("13", new String[]{"河北省"});
        AREA_CODES.put("14", new String[]{"山西省"});
        AREA_CODES.put("15", new String[]{"内蒙古自治区"});
        AREA_CODES.put("21", new String[]{"辽宁省"});
        AREA_CODES.put("22", new String[]{"吉林省"});
        AREA_CODES.put("23", new String[]{"黑龙江省"});
        AREA_CODES.put("31", new String[]{"上海市"});
        AREA_CODES.put("32", new String[]{"江苏省"});
        AREA_CODES.put("33", new String[]{"浙江省"});
        AREA_CODES.put("34", new String[]{"安徽省"});
        AREA_CODES.put("35", new String[]{"福建省"});
        AREA_CODES.put("36", new String[]{"江西省"});
        AREA_CODES.put("37", new String[]{"山东省"});
        AREA_CODES.put("41", new String[]{"河南省"});
        AREA_CODES.put("42", new String[]{"湖北省"});
        AREA_CODES.put("43", new String[]{"湖南省"});
        AREA_CODES.put("44", new String[]{"广东省"});
        AREA_CODES.put("45", new String[]{"广西壮族自治区"});
        AREA_CODES.put("46", new String[]{"海南省"});
        AREA_CODES.put("50", new String[]{"重庆市"});
        AREA_CODES.put("51", new String[]{"四川省"});
        AREA_CODES.put("52", new String[]{"贵州省"});
        AREA_CODES.put("53", new String[]{"云南省"});
        AREA_CODES.put("54", new String[]{"西藏自治区"});
        AREA_CODES.put("61", new String[]{"陕西省"});
        AREA_CODES.put("62", new String[]{"甘肃省"});
        AREA_CODES.put("63", new String[]{"青海省"});
        AREA_CODES.put("64", new String[]{"宁夏回族自治区"});
        AREA_CODES.put("65", new String[]{"新疆维吾尔自治区"});
        AREA_CODES.put("71", new String[]{"台湾省"});
        AREA_CODES.put("81", new String[]{"香港特别行政区"});
        AREA_CODES.put("82", new String[]{"澳门特别行政区"});
    }

    // 市级区域编码（示例，实际应更完整）
    private static final Map<String, String[]> CITY_CODES = new HashMap<>();
    static {
        // 北京市
        CITY_CODES.put("1101", new String[]{"市辖区"});
        CITY_CODES.put("1102", new String[]{"县"});
        // 上海市
        CITY_CODES.put("3101", new String[]{"市辖区"});
        CITY_CODES.put("3102", new String[]{"县"});
        // 更多地区可以继续添加...
    }

    private static final Random random = new Random();
    private static final int[] WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
    private static final char[] VERIFY_CODES = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

    /**
     * 生成随机身份证号
     */
    public static String generate() {
        return generate(null, null, null);
    }

    /**
     * 生成指定性别的身份证号
     */
    public static String generate(String gender) {
        return generate(null, null, gender);
    }

    /**
     * 生成指定年龄的身份证号
     */
    public static String generate(int age) {
        return generate(null, age, null);
    }

    /**
     * 生成指定地区、年龄、性别的身份证号
     */
    public static String generate(String area, Integer age, String gender) {
        // 1. 生成地区码（前6位）
        String areaCode = generateAreaCode(area);

        // 2. 生成出生日期（8位）
        String birthDate = generateBirthDate(age);

        // 3. 生成顺序码（3位）
        String sequenceCode = generateSequenceCode(gender);

        // 4. 前17位
        String first17 = areaCode + birthDate + sequenceCode;

        // 5. 生成校验码（第18位）
        char verifyCode = generateVerifyCode(first17);

        return first17 + verifyCode;
    }

    /**
     * 生成地区编码（6位）
     */
    private static String generateAreaCode(String specifiedArea) {
        if (specifiedArea != null && AREA_CODES.containsKey(specifiedArea)) {
            // 使用指定的省级编码
            String cityCode = getRandomCityCode(specifiedArea);
            return cityCode + String.format("%02d", random.nextInt(100));
        } else {
            // 随机选择省级编码
            List<String> provinces = new ArrayList<>(AREA_CODES.keySet());
            String province = provinces.get(random.nextInt(provinces.size()));
            String cityCode = getRandomCityCode(province);
            return cityCode + String.format("%02d", random.nextInt(100));
        }
    }

    private static String getRandomCityCode(String province) {
        // 查找该省份下的市级编码
        List<String> cityCodes = new ArrayList<>();
        for (String code : CITY_CODES.keySet()) {
            if (code.startsWith(province)) {
                cityCodes.add(code);
            }
        }

        if (!cityCodes.isEmpty()) {
            return cityCodes.get(random.nextInt(cityCodes.size()));
        } else {
            // 如果没有找到具体的市级编码，使用默认编码
            return province + "01";
        }
    }

    /**
     * 生成出生日期（8位）
     */
    private static String generateBirthDate(Integer specifiedAge) {
        Calendar calendar = Calendar.getInstance();

        if (specifiedAge != null) {
            // 指定年龄
            calendar.add(Calendar.YEAR, -specifiedAge);
        } else {
            // 随机年龄（18-70岁）
            int age = 18 + random.nextInt(53);
            calendar.add(Calendar.YEAR, -age);
        }

        // 随机月份和日期
        calendar.set(Calendar.MONTH, random.nextInt(12));
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, 1 + random.nextInt(maxDay));

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(calendar.getTime());
    }

    /**
     * 生成顺序码（3位）并包含性别信息
     */
    private static String generateSequenceCode(String gender) {
        int sequence = random.nextInt(999);

        if (gender != null) {
            // 根据性别设置顺序码的奇偶性
            // 男性为奇数，女性为偶数
            if ("男".equals(gender) || "male".equalsIgnoreCase(gender)) {
                // 确保是奇数
                if (sequence % 2 == 0) {
                    sequence = (sequence + 1) % 1000;
                }
            } else if ("女".equals(gender) || "female".equalsIgnoreCase(gender)) {
                // 确保是偶数
                if (sequence % 2 != 0) {
                    sequence = (sequence + 1) % 1000;
                }
            }
        }

        return String.format("%03d", sequence);
    }

    /**
     * 生成校验码
     */
    private static char generateVerifyCode(String first17) {
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (first17.charAt(i) - '0') * WEIGHT[i];
        }
        return VERIFY_CODES[sum % 11];
    }

    /**
     * 批量生成身份证号
     */
    public static List<String> generateBatch(int count) {
        return generateBatch(count, null, null, null);
    }

    public static List<String> generateBatch(int count, String area, Integer age, String gender) {
        List<String> idCards = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            idCards.add(generate(area, age, gender));
        }
        return idCards;
    }

    /**
     * 验证身份证号是否有效
     */
    public static boolean isValid(String idCard) {
        if (idCard == null || idCard.length() != 18) {
            return false;
        }

        // 检查前17位是否为数字
        String first17 = idCard.substring(0, 17);
        if (!first17.matches("\\d+")) {
            return false;
        }

        // 验证校验码
        char actualVerifyCode = idCard.charAt(17);
        char expectedVerifyCode = generateVerifyCode(first17);

        return actualVerifyCode == expectedVerifyCode;
    }

    /**
     * 从身份证号解析出生日期
     */
    public static Date parseBirthDate(String idCard) {
        if (!isValid(idCard)) {
            throw new IllegalArgumentException("无效的身份证号");
        }

        try {
            String birthDateStr = idCard.substring(6, 14);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            return sdf.parse(birthDateStr);
        } catch (Exception e) {
            throw new RuntimeException("解析出生日期失败", e);
        }
    }

    /**
     * 从身份证号解析性别
     */
    public static String parseGender(String idCard) {
        if (!isValid(idCard)) {
            throw new IllegalArgumentException("无效的身份证号");
        }

        String sequenceCode = idCard.substring(14, 17);
        int sequence = Integer.parseInt(sequenceCode);

        return (sequence % 2 == 0) ? "女" : "男";
    }

    /**
     * 从身份证号解析年龄
     */
    public static int parseAge(String idCard) {
        Date birthDate = parseBirthDate(idCard);
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthDate);

        Calendar now = Calendar.getInstance();

        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);

        // 如果生日还没过，年龄减1
        if (now.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)) {
            age--;
        }

        return age;
    }

    public static void main(String[] args) {
        String idCard=IDCardGenerator.generate();
        System.out.println(idCard);
    }
}
